#include "WString.h"
#include "BoardConf.h"
#include "mock/BoardAssemblyMock.h"
#include "mock/EthernetMock.h"
#include "mock/LoggerMock.h"
#include "mock/ServiceMock.h"
#include "mock/ServiceFactoryMock.h"
using ::testing::ReturnRef;
using ::testing::Eq;
using ::testing::ByRef;
using ::testing::ReturnPointee;

class BoardConfTest : public ::testing::Test {
public:
	BoardConfTest() : service(arduino, router, log), 
		factory(arduino, router, log),
		conf(arduino, router, factory, "groundFloor", log)
	{}
protected:
	ArduinoMock arduino;
	MessageRouterMock router;
	LoggerMock log;

	ServiceMock service;
	ServiceFactoryMock factory;
	BoardConf conf;
};

TEST_F(BoardConfTest, isInfrastructure){
	ASSERT_TRUE(conf.isInfrastructure());
}

TEST_F(BoardConfTest, ignoreOtherMessages){
	conf.onMessage("");
	conf.onMessage("{\"event\":\"montion\", \"id\":\"kitchen\"}");
	conf.onMessage("{\"cmd\":\"light\", \"id\":\"kitchen\", \"state\":\"on\"}");
}

TEST_F(BoardConfTest, addMontion){
	EXPECT_CALL(factory, createMontion(String("KitchenMontion"), 23))
		.Times(1)
		.WillOnce(ReturnRef(service));
	EXPECT_CALL(router, addService(Eq(ByRef(service))));
	
	conf.onMessage("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"Montion\", \"name\":\"KitchenMontion\", \"pin\":\"23\"}");
}
TEST_F(BoardConfTest, addAmbientController){
	EXPECT_CALL(factory, createAmbient(String("KitchenAmbientController"), String("buttonTrigger"), String("montionTrigger"), String("lightCircuit"))).
		Times(1).
		WillOnce(ReturnRef(service));
	EXPECT_CALL(router, addService(Eq(ByRef(service))));
	conf.onMessage("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"AmbientLight\", \"name\":\"KitchenAmbientController\", \"buttonTrigger\":\"buttonTrigger\", \"montionTrigger\":\"montionTrigger\", \"lightCircuit\":\"lightCircuit\"}");
}
TEST_F(BoardConfTest, addSimpleLightController){
	EXPECT_CALL(factory, createSimpleLight(String("KitchenSimpleLightController"), String("buttonTrigger"), String("lightCircuit"))).
		Times(1).
		WillOnce(ReturnRef(service));
	EXPECT_CALL(router, addService(Eq(ByRef(service))));
	conf.onMessage("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"SimpleLight\", \"name\":\"KitchenSimpleLightController\", \"buttonTrigger\":\"buttonTrigger\", \"lightCircuit\":\"lightCircuit\"}");
}
TEST_F(BoardConfTest, addButton){
	EXPECT_CALL(factory, createButton(String("KitchenButton"), 23)).
		Times(1).
		WillOnce(ReturnRef(service));
	EXPECT_CALL(router, addService(Eq(ByRef(service))));
		conf.onMessage("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"Button\", \"name\":\"KitchenButton\", \"pin\":\"23\"}");
}

TEST_F(BoardConfTest, addLightCircuit){
	EXPECT_CALL(factory, createLight(String("KitchenLight"), 23)).
		Times(1).
		WillOnce(ReturnRef(service));
	EXPECT_CALL(router, addService(Eq(ByRef(service))));
		conf.onMessage("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"LightCircuit\", \"name\":\"KitchenLight\", \"pin\":\"23\"}");
}

TEST_F(BoardConfTest, doNotAddUnknownService){
	conf.onMessage("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"UnknownService\", \"name\":\"KitchenAmbientController\", \"buttonTrigger\":\"buttonTrigger\", \"montionTrigger\":\"montionTrigger\", \"lightCircuit\":\"lightCircuit\"}");
}
TEST_F(BoardConfTest, removeService){
	EXPECT_CALL(factory, createLight(String("KitchenLight"), 23)).
		Times(1).
		WillOnce(ReturnRef(service));
	EXPECT_CALL(router, addService(Eq(ByRef(service))));
	conf.onMessage("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"LightCircuit\", \"name\":\"KitchenLight\", \"pin\":\"23\"}");
	
	EXPECT_CALL(router, removeService(String("KitchenLight")));
	conf.onMessage("{\"conf\":\"remove\", \"node\":\"groundFloor\", \"name\":\"KitchenLight\"}");
}


TEST_F(BoardConfTest, removeAllServices){
	EXPECT_CALL(factory, createLight(String("KitchenLight"), 23)).
		Times(1).
		WillOnce(ReturnRef(service));
	EXPECT_CALL(router, addService(Eq(ByRef(service))));
	conf.onMessage("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"LightCircuit\", \"name\":\"KitchenLight\", \"pin\":\"23\"}");

	EXPECT_CALL(factory, createLight(String("KitchenLight1"), 22)).
		Times(1).
		WillOnce(ReturnRef(service));
	EXPECT_CALL(router, addService(Eq(ByRef(service))));
	conf.onMessage("{\"conf\":\"add\", \"node\":\"groundFloor\", \"type\":\"LightCircuit\", \"name\":\"KitchenLight1\", \"pin\":\"22\"}");
	
	Service s1(arduino, router, "KitchenLight", log), s2(arduino, router, "KitchenLight1", log);
	EXPECT_CALL(router, getServicesSize()).WillOnce(Return(2));
	EXPECT_CALL(router, getService(0)).WillRepeatedly(Return(&s1));
	EXPECT_CALL(router, getService(1)).WillRepeatedly(Return(&s2));
		
	EXPECT_CALL(router, removeService(String("KitchenLight")));
	EXPECT_CALL(router, removeService(String("KitchenLight1")));
	conf.onMessage("{\"conf\":\"removeAll\"}");
}